﻿#ifndef _CELL_EPOLL_HPP_
#define _CELL_EPOLL_HPP_

#if __linux__
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include "CELLLog.hpp"
#include <string.h>
#include <errno.h>
#include "CELLClient.h"

class CELLEpoll
{
public:
	~CELLEpoll()
	{
		destory();
	}

	int create(int nMaxEvents)
	{
		if (_epfd > 0)
		{
			destory();
			CELLLog_Warning("CELLEpoll create has destory old epfd");
		}
		_nMaxEvents = nMaxEvents;
		_pEvents = new epoll_event[nMaxEvents];
		_epfd = epoll_create(nMaxEvents);
		if (_epfd == -1)
		{
			CELLLog_pError("CELLEpoll epoll_create error: %s", strerror(errno));
		}
		return _epfd;
	}

	void destory()
	{
		if (_epfd > 0)
		{
			close(_epfd);
			_epfd = -1;
		}
		if (_pEvents)
		{
			delete[] _pEvents;
			_pEvents = nullptr;
		}
	}

	int ctl(int opt, int sockfd, uint32_t events)
	{
		epoll_event ev;
		ev.events = events;
		ev.data.fd = sockfd;
		int ret = epoll_ctl(_epfd, opt, sockfd, &ev);
		if (ret == -1)
		{
			CELLLog_pError("CELLEpoll ctl1");
		}
		return ret;
	}

	int ctl(int opt, CELLClient* pClient, uint32_t events)
	{
		epoll_event ev;
		ev.events = events;
		ev.data.ptr = pClient;
		int ret = epoll_ctl(_epfd, opt, pClient->sockfd(), &ev);
		if (ret == -1)
		{
			CELLLog_pError("CELLEpoll ctl2");
		}
		return ret;
	}

	int wait(int milliseconds = 0)
	{
		int n = epoll_wait(_epfd, _pEvents, _nMaxEvents, milliseconds);
		if (n == -1)
		{
			if (errno == EINTR)
			{
				return 0;
			}

			CELLLog_pError("CELLEpoll wait");
		}
		return n;
	}

	epoll_event* events()
	{
		return _pEvents;
	}
private:
	// epoll树根节点
	int _epfd = -1;
	// epoll_event数组指针
	epoll_event* _pEvents = nullptr;
	// 用于wait函数
	int _nMaxEvents = -1;
};

#endif // #if __LINUX__

#endif // #ifndef _CELL_EPOLL_HPP_
